package com.tonann.app.refrigerator;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.tonann.app.domain.AppDevice;
import com.tonann.app.domain.AppSensor;
import com.tonann.app.mqtt.dao.DataWriteBody;
import com.tonann.app.mqtt.singleServer.MqttConfig;
import com.tonann.app.service.IAppDeviceService;
import com.tonann.app.service.IAppSensorService;
import com.tonann.app.service.impl.AppSensorServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 楚秀接口
 *
 * @author c-sunshuai
 */
@Component("chuXiuSyncTask")
public class ChuXiuSyncTask {
    /**
     * 深圳华大智造
     */
    @Value("${mgi.iot.cxHttp.tokenName:eyJhbGciOiJIUzUxMiJ9}")
    private String tokenName;

    @Value("${mgi.iot.cxHttp.userid:40}")
    private String userid;

    @Resource
    private IAppDeviceService appDeviceService;

    @Resource
    private IAppSensorService appSensorService;
    @Resource
    private  MqttConfig.MqttGateway mqttGateway;

    /**
     * 查询设备仪器属性
     */
    public void getDeviceProperty() throws NoSuchAlgorithmException, KeyManagementException {
        ignoreSSL();
        Map<String, String> map = new HashMap<>();
        Map<String, AppSensor> sensorMap = new HashMap<>();
        RestTemplate restTemplate = new RestTemplate();
        String url = "https://data.chuxou.com/openapi/equipment/status";
        List<EquipmentVO> voList = new ArrayList<>();
        voList = this.getEquipmentChuXiuList(1, voList);
        AppDevice appDevice = new AppDevice();
        appDevice.setType("16");
        List<AppDevice> deviceList = appDeviceService.selectAppDeviceAll(appDevice);
        if (deviceList != null) {
            for (AppDevice device : deviceList) {
                List<AppSensor> appSensorList = appSensorService.selectAppSensorAllListByDeviceId(device.getDeviceId());
                if (appSensorList != null) {
                    for (AppSensor sensor : appSensorList) {
                        if (sensor.getTdCode() != null && sensor.getSensorType() != null && sensor.getSensorType().equals("1")) {
                            sensorMap.put(sensor.getTdCode(), sensor);
                        }
                    }
                }
            }
        }
        Set<String> set = sensorMap.keySet();
        for (EquipmentVO vo : voList) {
            for (String str : set) {
                if (vo.getEquipmentNo().equals(str)) {
                    map.put(str, vo.getEquipmentId().toString());
                }
            }
        }
//        if (!voList.isEmpty()) {
//            for (EquipmentVO vo : voList) {
        List<AppSensor> updateList = new ArrayList<>();
        for (String str : set) {
//                String deviceInfoId = vo.getEquipmentId().toString();
            String deviceInfoId = map.get(str);
            if (deviceInfoId == null) {
                continue;
            }
            Map<String, Object> requestParam = new HashMap<String, Object>();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("equipmentId", deviceInfoId);
            requestParam.put("id", userid);
            requestParam.put("json", jsonObject);
            //如果同步失败，再同步三次
            long timestamp = new Date().getTime() - 10000;
            String token = MD5Utils.getMD5Str(tokenName + timestamp);
            requestParam.put("timestamp", timestamp);
            requestParam.put("token", token);
            MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
            paramsMap.add("id", userid);
            paramsMap.add("json", jsonObject);
            paramsMap.add("timestamp", timestamp);
            paramsMap.add("token", token);
            //设置请求信息
            RequestEntity requestEntity = RequestEntity
                    .post(URI.create(""))
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                    .accept(MediaType.ALL)
                    .acceptCharset(StandardCharsets.UTF_8)
                    .body(paramsMap);
//                String response = HttpClient.doPost(url, requestParam);
            String response = restTemplate.postForObject(url, requestEntity, String.class);
//            	 String response = HttpClient.doPost(url, requestParam);
//            System.out.println("*********************设备状态--开始********************");
//            System.out.println(paramsMap.toString());
//            System.out.println(response);
            try {
                Gson gson = new Gson();
                EquipmentStatus status = gson.fromJson(response, EquipmentStatus.class);
                if (status != null && status.getItems() != null && status.getItems().getEquipment() != null) {
                    Equipment equipment = status.getItems().getEquipment();
                    String value1 = null;
                    if (equipment.getMonitorType1() == 1) {
                        value1 = equipment.getMonitorValue1().toString();
                    } else if (equipment.getMonitorType2() == 1) {
                        value1 = equipment.getMonitorValue2();
                    } else if (equipment.getMonitorType3() == 1) {
                        value1 = equipment.getMonitorValue3();
                    } else if (equipment.getMonitorType4() == 1) {
                        value1 = equipment.getMonitorValue4();
                    }
                    AppSensor sensor = sensorMap.get(str);
                    if (sensor != null) {
                        sensor.setValue(value1);
//                        sensor.setUpdateTime(new DateTime(equipment.getReportDate()));
                        if (sensor.getMqttWriteTopic() != null
                                && sensor.getMqttDeviceChannel() != null
                                && sensor.getMqttDeviceName() != null
                                && sensor.getMqttDeviceTag() != null) {
                            //发送MQTT
                            String key = sensor.getMqttDeviceChannel() + "." + sensor.getMqttDeviceName() + "." + sensor.getMqttDeviceTag();
                            List<DataWriteBody> dataBodyList = new ArrayList<>();
                            DataWriteBody dataBody = new DataWriteBody();
                            dataBody.setId(key);
                            dataBody.setV(sensor.getValue());
                            dataBodyList.add(dataBody);
                            try {
                                mqttGateway.sendToMqtt(sensor.getMqttWriteTopic(), false, JSONObject.toJSONString(dataBodyList));
                            }catch (Exception e){}
//                            Logger log = LoggerFactory.getLogger(AppSensorServiceImpl.class);
//                            log.error("mqtt下发数据：" + JSONObject.toJSONString(dataBodyList));
                        }
                        updateList.add(sensor);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
//            System.out.println("*********************设备状态--结束********************");
        }
        if (!updateList.isEmpty()) {
            appSensorService.updateByModbusList(updateList);
        }
    }

    /**
     * 更新设备属性
     *
     * @param deviceInfoId
     */
    private boolean updateDeviceProperty(String deviceInfoId, String response, long lastRequestTime, String deviceCode, String deviceName) {
        Gson gson = new Gson();
        CXEquipmentProperty r = gson.fromJson(response, CXEquipmentProperty.class);

        ObjectMapper objectMapper = new ObjectMapper();
        String property = "{}";
        try {
            if (r.getItems() == null) {
                return false;
            }
            Object equipmentValue = r.getItems().getEquipment();
            property = objectMapper.writeValueAsString(equipmentValue);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            property = null;
        }

        if (StrUtil.isNotEmpty(property)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date dt = new Date(lastRequestTime);
            JSONObject data = JSONObject.parseObject(property);

            //上报时间
            data.getString("ReportDate");

            //温度数据
            String value1 = data.getString("MonitorValue1");
            String status1 = data.getString("RunStatus1");//设备自己监测的异常状态  1.0正常


            //湿度
            String value2 = data.getString("MonitorValue2");
            String status2 = data.getString("RunStatus2");//设备自己监测的异常状态  1.0正常


        }


        return true;
    }


    /**
     * {"equipmentId":"7616","equipmentNo":"11110080004321","timeFrom":"2021-03-11 00:00:00","timeTo":"2021-03-12 00:00:00","equipmentVer":"2"}
     * 查询设备仪器
     */
    public static void getDeviceInfo2() {

        String url = "https://data.chuxou.com/openapi/equipment/data";
        Map<String, Object> requestParam = new HashMap<String, Object>();
        long timestamp = new Date().getTime() - 10000;
        String token = MD5Utils.getMD5Str("eyJhbGciOiJIUzUxMiJ9" + timestamp);
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("equipmentId", "7616");
        jsonObject.put("equipmentNo", "11110080004321");
        jsonObject.put("timeFrom", "2021-03-01 00:00:00");
        jsonObject.put("timeTo", "2021-03-22 00:00:00");
        jsonObject.put("equipmentVer", "2");

        requestParam.put("token", token);
        requestParam.put("id", "40");
        requestParam.put("timestamp", timestamp);
        requestParam.put("json", jsonObject);
//        String response = HttpClient.doPost(url, requestParam);
        /*
         * System.out.println("*********************设备历史记录********************");
         * System.out.println(requestParam.toString()); System.out.println(response);
         */
    }


    //获取楚秀List
    //楚秀接口每次请求100条，仪器数量可能大于100，多次请求
    public List<EquipmentVO> getEquipmentChuXiuList(Integer num, List<EquipmentVO> resEquipments) throws NoSuchAlgorithmException, KeyManagementException {
        ignoreSSL();
        RestTemplate restTemplate = new RestTemplate();
        List<EquipmentVO> equipments = resEquipments;
        List<EquipmentVO> newEquipments = new ArrayList<>();
        String url = "https://data.chuxou.com/openapi/equipment/list";
        Map<String, Object> requestParam = new HashMap<String, Object>();
        long timestamp = new Date().getTime() - 10000;
        String offsetValue = String.valueOf(num);//从第num条开始取值
        String token = MD5Utils.getMD5Str(tokenName + timestamp);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("offset", offsetValue);
        requestParam.put("token", token);
        requestParam.put("id", userid);
        requestParam.put("timestamp", timestamp);
        requestParam.put("json", jsonObject);
        MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
        jsonObject.put("offset", offsetValue);
        paramsMap.add("token", token);
        paramsMap.add("id", userid);
        paramsMap.add("timestamp", timestamp);
        paramsMap.add("json", jsonObject);
        //设置请求信息
        RequestEntity requestEntity = RequestEntity
                .post(URI.create(""))
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .accept(MediaType.ALL)
                .acceptCharset(StandardCharsets.UTF_8)
                .body(paramsMap);
//                String response = HttpClient.doPost(url, requestParam);
        String response = restTemplate.postForObject(url, requestEntity, String.class);
//        String response = HttpClient.doPost(url, requestParam);
//        System.out.println("*********************设备列表状态--开始********************");
//        System.out.println(paramsMap.toString());
//        System.out.println(response);
//        System.out.println("*********************设备列表状态--结束********************");
        Gson gson = new Gson();
        CXEquipment r = gson.fromJson(response, CXEquipment.class);
        if (r != null && r.getItems()!= null && r.getItems().getEquipments() != null) {
            newEquipments = r.getItems().getEquipments();
            equipments.addAll(newEquipments);
            num = equipments.size();
            //请求条数为0.则停止
            if (!equipments.isEmpty() && equipments.size() % 100 == 0 && !newEquipments.isEmpty()) {
                equipments = getEquipmentChuXiuList(num + 1, equipments);
            }
        }
        return equipments;
    }
//
//    public static void main(String[] args) {
//        String tokenName = "eyJhbGciOiJIUzUxMiJ9";
//        String userid = "40";
//        for (int i = 0; i < 1000; i++) {
//
//            String url = "https://data.chuxou.com/openapi/equipment/status";
//
//            Map<String, Object> requestParam = new HashMap<String, Object>();
//
//            JSONObject jsonObject = new JSONObject();
//            jsonObject.put("equipmentId", "21974");
//
//            requestParam.put("id", userid);
//
//            requestParam.put("json", jsonObject);
//
//            boolean isOk = true;
//            for (int j = 0; j < 3; j++) {
//                long timestamp = new Date().getTime() - 5000;
//                String token = MD5Utils.getMD5Str(tokenName + timestamp);
//                requestParam.put("timestamp", timestamp);
//                requestParam.put("token", token);
//                String response = HttpClient.doPost(url, requestParam);
//                System.out.println(i + ":" + response);
//                Gson gson = new Gson();
//                CXEquipmentProperty r = gson.fromJson(response, CXEquipmentProperty.class);
//
//                ObjectMapper objectMapper = new ObjectMapper();
//                String property = "{}";
//
//
//                if (r.getItems() == null) {
//                    isOk = false;
//                    continue;
//                } else {
//                    isOk = true;
//                    break;
//                }
//
//
//            }
//            if (!isOk) {
//                return;
//            }
//
//
//        }
//
//    }

    public void ignoreSSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }};
        sslContext.init(null, trustManagers, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
    }
}
